package main

import (
	"bytes"
	"emulator"
	"encoding/json"
	"fmt"
	"gentk"
	"github.com/garyburd/redigo/redis"
	"github.com/gocql/gocql"
	"log"
	"net/http"
	"rhelper"
	"time"
)

// message

// MsgHash   = "w:m:"
// MsgURHash = "w:mu:"

// MsgIdHolder = "w:i:mid"
// // TaskIdHolder = "w:i:tid"

// PowerReport = "w:s:"

// ApnsToken = "w:apns:tk"

// WebAccount = "w:webAcc:"

// EVRelay = "w:ev:relay:"

// OnlineDev = "w:ond:"
// // OnlineUser = "w:onu:"

// WaitKey = "w:wait:"

// //account sort set
// AccountSortSet = "w:sset:a"
const (
	serverUrl = "http://127.0.0.1:4002"

	// tablesName = map[string]
)

var (
	cluster *gocql.ClusterConfig

	tables = []string{"w:c", "w:p", "w:i:pid", "w:a", "w:u", "w:i:uid",
		"w:m", "w:mu", "w:i:mid", "w:s", "w:apns:tk", "w:webAcc",
		"w:ev:relay", "w:ond", "w:wait", "w:sset:a"}

	createAccTableCql = "CREATE TABLE IF NOT EXISTs acc (acc text primary key, id text, ip text, registerTime text)"
)

func main() {
	log.Println("start test ...")
	// initCassandra()
	// createTables()

	//testGetPowerReport()
	//testResetDev()
	//testSoftRestore()
	//testSetTrigger()
	//testDelTrigger()
	//testLoadTrigger()
	//testClearTriggerCount()
	//testLoadTriggerCount()
	//message.SendGmail("1052441607@qq.com", "hellow wrold")
	//testRedis("riguang")
	//testSetCtlFlags()
	//getCurrentDateTime()
	//testLogin()
	// testRegister()
	//testJSON()
	//testRedis("riguang")
	// testReadRedisData()
	// transferAccTable()
	// redis2Cassandra.InitDataBase()
	// emulator.StartEmulator()
	emulator.Test()
	return
}

func initCassandra() {
	cluster = gocql.NewCluster("127.0.0.1")
	// cluster.Keyspace = "demo"

	session, _ := cluster.CreateSession()
	defer session.Close()

	queryString := "CREATE KEYSPACE IF NOT EXISTS wswitch  WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}"
	err := session.Query(queryString).Exec()
	if err != nil {
		log.Fatal(err)
	}
}

func createTables() {
	// createHashTable(rhelper.ControllerHash, "cid")
	// createHashTable(rhelper.AccountHash, "account")
	// createHashTable(rhelper.UserHash, "id")
	// createHashTable(rhelper.PlanHash, "cid")
	// createHashTable(rhelper.MsgHash, "uid")
	// createHashTable(rhelper.MsgURHash, "mid")
	query(createAccTableCql)

}

func splictKey(preKey string, key string) string {
	strSize := len(preKey)
	return key[strSize:]
}

func transferAccTable() {
	keys := testReadAllkey(rhelper.AccountHash + "*")

	rconn := rhelper.Pool().Get()
	defer rconn.Close()
	log.Println("keys: ", keys)

	for _, key := range keys {

		values, err := redis.Strings(rconn.Do("HMGET", key, "id", "ip", "rigisterTime"))
		if err != nil {
			log.Println("testReadHashType failed, error:", err)
		}

		acc := splictKey(rhelper.AccountHash, key)
		id := values[0]
		ip := values[1]
		rigisterTime := values[2]

		queryString := "INSERT INTO acc (acc, id, ip, registerTime) VALUES ( '" + acc + "', '" + id + "', '" + ip + "', '" + rigisterTime + "');"

		query(queryString)

	}
}

// func testControllerTable() {

// }
// func createTables() {
// 	session, _ := cluster.CreateSession()
// 	defer session.Close()

// 	for _, table := range tables {
// 		queryString := "CREATE TABLE IF NOT EXISTS " + table
// 		err := session.Query(queryString).Exec()
// 		if err != nil {
// 			log.Fatal(err)
// 		}
// 	}
// }

func testReadAllkey(preKey string) []string {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	keys, err := redis.Strings(rconn.Do("KEYS", preKey))
	if err != nil {
		log.Println("testReadAllkey failed, error:", err)
		return []string{}
	}

	return keys
}

func testReadKeyType(key string) string {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	keyType, err := redis.String(rconn.Do("type", key))
	if err != nil {
		log.Println("testReadAllkey failed, error:", err)
		return ""
	}

	return keyType
}

func testReadStringType(key string) string {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	stringValue, err := redis.String(rconn.Do("GET", key))
	if err != nil {
		log.Println("testReadStringType failed, error:", err)
		return ""
	}

	return stringValue
}

func testReadHashType(key string) string {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	stringMap, err := redis.StringMap(rconn.Do("HGETALL", key))
	if err != nil {
		log.Println("testReadHashType failed, error:", err)
		return ""
	}

	// jsonString, err := gocql.Marshal(gocql.TypeInfo.Type(), stringMap)
	// if err != nil {
	// 	log.Println("err: ", err)
	// }
	jsonString, err := json.Marshal(stringMap)
	if err != nil {
		log.Println("err: ", err)
	}

	log.Printf("testReadHashType value: %s", jsonString)
	return string(jsonString)
}

func testReadSetType(key string) interface{} {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	value, err := redis.Strings(rconn.Do("SMEMBERS", key))
	if err != nil {
		log.Println("testReadSetType failed, error:", err)
		return nil
	}

	return value
}

// func testReadZSetType(key string) interface{} {
// 	rconn := rhelper.Pool().Get()
// 	defer rconn.Close()

// 	value, err := redis.Strings(rconn.Do("SMEMBERS", key))
// 	if err != nil {
// 		log.Println("testReadSetType failed, error:", err)
// 		return nil
// 	}

// 	return value
// }

func testReadListType(key string) interface{} {
	// log.Println("testReadSetListType key: ", key)
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	length, err := redis.Int(rconn.Do("LLEN", key))
	if err != nil {
		log.Println("testReadSetListType failed, error:", err)
		return nil
	}

	if length < 1 {
		log.Println("length is 0")
		return nil
	}

	value, err := redis.Strings(rconn.Do("LRANGE", key, 0, length-1))
	if err != nil {
		log.Println("testReadSetListType failed, error:", err)
		return nil
	}
	return value
}

func testReadKeyValue(key string, keyType string) interface{} {
	switch keyType {
	case "string":
		return testReadStringType(key)

	case "hash":
		return testReadHashType(key)

	case "set":
		return testReadSetType(key)

	case "zset":
		return testReadSetType(key)

	case "list":
		return testReadListType(key)
	}

	return nil
}

func saveStringType(key string, value string) {
	log.Printf("saveStringType, key: %s, value: %s", key, value)
	// cluster.Keyspace = "wswitch"
	// session, _ := cluster.CreateSession()
	// defer session.Close()

	queryString := "INSERT INTO wstring (wkey, content) VALUES ( '" + key + "', '" + value + "');"
	// +primaryKey + " text PRIMARY KEY,"
	// +" content text);"
	query(queryString)
}

func saveHashType(key string, value string) {

	log.Printf("saveHashType key: %s, value: %s", key, value)
	// cluster.Keyspace = "wswitch"
	// session, _ := cluster.CreateSession()
	// defer session.Close()

	queryString := "INSERT INTO wstring (wkey, content) VALUES ( '" + key + "', " + value + ");"

	query(queryString)
}

func testReadRedisData() {

	keys := testReadAllkey("*")

	for _, key := range keys {
		keyType := testReadKeyType(key)
		value := testReadKeyValue(key, keyType)

		switch keyType {
		case "string":
			saveStringType(key, fmt.Sprintf("%v", value))
			break
		case "hash":
			saveStringType(key, fmt.Sprintf("%v", value))
			break
		case "set":
			break
		case "list":
			break
		}
	}
}

func createTextTable(tableName string, primaryKey string) {
	queryString := "CREATE TABLE IF NOT EXISTS " + tableName + " (" + primaryKey + " text PRIMARY KEY, content text);"
	query(queryString)
}

func createHashTable(tableName string, primaryKey string) {
	queryString := "CREATE TABLE IF NOT EXISTS " + tableName + " (" + primaryKey + " text PRIMARY KEY, content map<text, text>);"
	query(queryString)

}

func createSetTable(tableName string, primaryKey string) {
	queryString := "CREATE TABLE IF NOT EXISTS " + tableName + " (" + primaryKey + " text PRIMARY KEY, content set<text>);"
	query(queryString)
}

func createListTable(tableName string, primaryKey string) {
	queryString := "CREATE TABLE IF NOT EXISTS " + tableName + " (" + primaryKey + " text PRIMARY KEY, content list<text>);"
	query(queryString)
}

func query(queryString string) {
	cluster.Keyspace = "wswitch"
	session, _ := cluster.CreateSession()
	defer session.Close()

	err := session.Query(queryString).Exec()
	if err != nil {
		log.Fatal(err)
	}
}

func testWriteHash2Cassandra(key string, value map[string]string) {

}

func testWriteSet2Cassandra(key string, value map[string]string) {

}

func testWriteList2Cassandra(key string, value map[string]string) {

}

// func testPowerReport() {

// 	report := devserv.PowerReportMsg{}
// 	report.Energy = "873"
// 	report.Duration = "183"

// 	c := devserv.Controller{}
// 	c.Id = "1234567899"

// 	c.SavePowerReportNew(report)
// }

func testGetPowerReport() {
	//reports := userserv.GetReports("566ee603-ffff-ff7f-ffff-ff7fffffff7f", "2015112401", "2015112718")
	//log.Println("reports", reports)
}

func testResetDev() {
	var jsonStr = []byte(`{"cid":"baaccf38-d4c5-4668-9111-d93691a3a456"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/resetDev", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000009")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testSoftRestore() {
	var jsonStr = []byte(`{"cid":"048c6439-d7ac-434b-ab82-fe4ce2192945"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/softRestore", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000009")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

type Trigger struct {
	Cid               string  `json:"cid"`
	Above             float64 `json:"above"`
	Below             float64 `json:"below"`
	AboveAction       bool    `json:"aboveAction"`
	BelowAction       bool    `json:"belowAction"`
	IsClosePlug       bool    `json:"isClosePlug"`
	IsSendMail        bool    `json:"isSendMail"`
	IsPushNotify      bool    `json:"isPushNotify"`
	AboveTriggerCount int     `json:"aboveTriggerCount"`
	belowTriggerCount int     `json:"BelowTriggerCount"`
}

func testSetTrigger() {
	var jsonStr = []byte(`{"cid":"79cdbd5b-6e65-4965-b234-d85d0b4a1e6e",
		"above":20, "below":0, "aboveAction":true, "belowAction":false, "isClosePlug":true, "isSendMail":false, "isPushNotify":true}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/setTrigger", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testDelTrigger() {
	var jsonStr = []byte(`{"cid":"79cdbd5b-6e65-4965-b234-d85d0b4a1e6e"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/deleteTrigger", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testLoadTrigger() {
	var jsonStr = []byte(`{"cid":"79cdbd5b-6e65-4965-b234-d85d0b4a1e6e"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/loadTrigger", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testClearTriggerCount() {
	var jsonStr = []byte(`{"cid":"79cdbd5b-6e65-4965-b234-d85d0b4a1e6e"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/clearTriggerCount", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testLoadTriggerCount() {
	var jsonStr = []byte(`{"cid":"79cdbd5b-6e65-4965-b234-d85d0b4a1e6e"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/loadTriggerCount", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testRedis(account string) {
	// log.Printf("account:%s", account)

	// redisClient := rhelper.RedisClient()

	// // id, err := redis.String(rconn.Do("HGET", rhelper.AccountHash+account, "id"))
	// id, err := redisClient.HGet(rhelper.AccountHash+account, "id").Result()
	// if err != nil && err != redis.Nil {
	// 	log.Println("verifyAccount err:", err)
	// 	return
	// }

	// log.Println("verifyAccount id:", id)

}

type Flags struct {
	Cid  string `json:"cid"`
	Flag string `json:"flag"`
	Set  string `json:"set"`
	Uri  string `json:"uri"`
}

func testSetCtlFlags() {
	var jsonStr = []byte(`{"cid":"048c6439-d7ac-434b-ab82-fe4ce2192945","flag":"0", "set":0, "uri":"/setCtlFlags"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/setCtlFlags", bytes.NewBuffer(jsonStr))

	token := gentk.GenTK("1000001")
	req.Header.Add("tk", token)

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

type DeviceDateTime struct {
	Error        int
	Weekday      int
	Year         int
	Month        int
	Day          int
	MilliSeconds int
}

func getCurrentDateTime() *DeviceDateTime {
	dt := DeviceDateTime{}
	now := time.Now()
	dt.Weekday = int(now.UTC().Weekday())
	dt.Month = int(now.UTC().Month())
	dt.Year = now.UTC().Year()
	dt.Day = now.UTC().Day()

	middleNigh := time.Date(dt.Year, time.Month(dt.Month),
		dt.Day, 0, 0, 0, 0, time.UTC)
	d := (now.Sub(middleNigh))
	log.Println("d: ", d)
	dt.MilliSeconds = int(d.Nanoseconds() / 1000000)
	return &dt
}

func testLogin() {
	var jsonStr = []byte(`{"account":"riguang","password":"123456"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/login", bytes.NewBuffer(jsonStr))

	//token := gentk.GenTK("1000001")
	//req.Header.Add("tk", token)
	req.Header.Add("account", "riguang")
	req.Header.Add("password", "123456")

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testRegister() {
	var jsonStr = []byte(`{"account":"riguang","password":"123456"}`)
	client := &http.Client{Timeout: time.Second * 60}
	req, err := http.NewRequest("GET", serverUrl+"/register", bytes.NewBuffer(jsonStr))

	//token := gentk.GenTK("1000001")
	//req.Header.Add("tk", token)
	req.Header.Add("account", "rigu---")
	req.Header.Add("password", "123---")

	resp, err := client.Do(req)
	if err != nil {
		log.Println("err: ", err)
		return
	}

	if resp.StatusCode != 200 {
		log.Println("resp.StatusCode != 200")
		return
	}

	errcode := resp.Header.Get("error")
	if errcode != "" {
		log.Println("errorcode: ", errcode)
		return
	}

	body := make([]byte, 1024)
	read, err := resp.Body.Read(body)
	if err != nil && read < 1 {
		log.Println("read message body err: ", err)
		return
	}

	body = body[:read]
	log.Println("body: ", string(body))
}

func testJSON() {
	type LoginInfo struct {
		Account    string `json:"Account"`
		Password   string `json:"Password"`
		OS         string `json:"OS"`
		AppVersion string `json:"AppVersion"`
		DevToken   string `json:"DevToken"`
	}

	var jsonStr = []byte(`{"Account":"mikefarag01","Password":"Soprano1", "OS":"iOS 9.2.1", "AppVersion":"1.53", "DevToken":"7db67072a03025fc414db0b29303281026fe86110c99bf678460bfeda4f610f4"}`)

	var loginInfo LoginInfo
	err := json.Unmarshal(jsonStr, &loginInfo)
	if err != nil {
		log.Println("onUpgradeDevice failed, json decode failed:", err)
		return
	}
	log.Println(loginInfo)
	log.Println("dev token: ", loginInfo.DevToken)

}
